using System.Reflection;
using System.Text.Json.Nodes;
using FastDevTemplate.Api.Attribute;
using FastDevTemplate.Api.Base;
using FastDevTemplate.Service.Interface;
using FastDevTemplate.Service.Interface.DTO;

namespace FastDevTemplate.Api;

public static class InitializeData
{
    public static void LoadPermissions(this IServiceCollection service)
    {
        var controllerTypes = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(assembly => assembly.GetTypes()
                .Where(type => typeof(BaseController).IsAssignableFrom(type) && !type.IsAbstract));

        var attributes = controllerTypes
            .SelectMany(controllerType => controllerType
                .GetMethods()
                .SelectMany(methodInfo => methodInfo
                    .GetCustomAttributes<PermissionVerificationAttribute>()))
            .DistinctBy(item => item.ID)
            .Where(item => !String.IsNullOrEmpty(item.ID));

        var clientGroup = attributes.GroupBy(item => item.Client);
        foreach (var group in clientGroup)
        {
            using var serviceProvider = service.BuildServiceProvider();
            var permissionService = serviceProvider.GetService<IPermissionService>() ??
                                    throw new ApplicationException(
                                        "LoadPurviewData: The IPurviewService instance is not obtained.");
            try
            {
                var count = permissionService.SetListByServiceAsync(group.Key,
                    group.Select(item => new PermissionAddDto()
                    {
                        ID = item.ID,
                        Describe = item.Describe
                    }).ToList()).Result;
            }
            catch
            {
                Console.WriteLine("Data Access: Purview The initial data exists.");
            }
        }
    }

    public static void LoadDefaultRoles(this IServiceCollection service, string jsonPath = "defaultdata.json")
    {
        var jsonString = File.ReadAllText(jsonPath);
        var docment = JsonNode.Parse(jsonString)!;
        bool? isUseDefultData = docment["UseDefaultData"]?.GetValue<bool>();
        if (isUseDefultData ?? false)
        {
            using var serviceProvider = service.BuildServiceProvider();

            #region role base data

            var roleService = serviceProvider.GetRequiredService<IRoleService>();
            var roleNodes = docment["Role"]?.AsArray() ?? new JsonArray();
            foreach (var role in roleNodes)
            {
                var roleID = role!["ID"]?.GetValue<string>()
                             ?? throw new ArgumentException("DefaultRole: roleType is null");

                var roleDescribe = role!["Describe"]?.GetValue<string>()
                                   ?? throw new ArgumentException("DefaultRole: roleDescribe is null");

                var rolePermissionSet = role["Permissions"]?.AsArray()
                    .Select(item => item!.GetValue<string>()).ToList() ?? new List<string>();
                
                var res = roleService.Add(new RoleAddDto()
                {
                    ID = roleID,
                    Describe = roleDescribe
                });
                if (res != null)
                {
                    var count = roleService.AddPermissionListAsync(roleID, rolePermissionSet.ToArray()).Result;
                }

            }

            #endregion
        }
    }

    public static void LoadDefaultUsers(this IServiceCollection service, string jsonPath = "defaultdata.json")
    {
        var jsonString = File.ReadAllText(jsonPath);
        var docment = JsonNode.Parse(jsonString)!;
        bool? isUseDefultData = docment["UseDefaultData"]?.GetValue<bool>();
        if (isUseDefultData ?? false)
        {
            using var serviceProvider = service.BuildServiceProvider();

            #region user base data

            var userService = serviceProvider.GetRequiredService<IUserService>();
            var userNodes = docment["User"]?.AsArray() ?? new JsonArray();
            foreach (var user in userNodes)
            {
                var userName = user!["UserName"]?.GetValue<string>()
                               ?? throw new ArgumentException("DefaultUser: userName is null");

                var userPassword = user!["Password"]?.GetValue<string>()
                                   ?? throw new ArgumentException("DefaultUser: userPassword is null");

                var userRoleSet = user["Role"]?.AsArray()
                    .Select(item => item!.GetValue<string>()).ToList() ?? new List<string>();

                var res = userService.Add(new UserAddDto()
                {
                    UserName = userName,
                    Password = userPassword
                });
                if (res != null)
                {
                    var count = userService.AddRoleListAsync(res.ID, userRoleSet.ToArray()).Result;
                }
            }

            #endregion
        }
        
    }
}